// file:include/arch/x86.h
// autor:jiang xinpeng
// time:2020.12.23
// copyright:(C) 2020-2050 by jiang xinpeng,All right are reserved.

#ifndef ARCH_X86_H
#define ARCH_X86_H

#include <lib/type.h>

// there are function declare about read data from io port
extern __attribute__((optimize("O0"))) uint8_t _In8(uint16_t port);
extern __attribute__((optimize("O0"))) uint16_t _In16(uint16_t port);
extern __attribute__((optimize("O0"))) uint32_t _In32(uint16_t port);

// there are function declare about write data  to io port
extern __attribute__((optimize("O0"))) void _Out8(uint16_t port, uint8_t data);
extern __attribute__((optimize("O0"))) void _Out16(uint16_t port, uint16_t data);
extern __attribute__((optimize("O0"))) void _Out32(uint16_t port, uint32_t data);

// interrupt control
extern __attribute__((optimize("O0"))) void EnInterrupt();
extern __attribute__((optimize("O0"))) void DisInterrupt();

// tr
extern __attribute__((optimize("O0"))) void LoadTR(uint32_t tr);
extern __attribute__((optimize("O0"))) void StoreTR(uint32_t tr);

// controller register group
extern __attribute__((optimize("O0"))) uint32_t ReadCR0();
extern __attribute__((optimize("O0"))) uint32_t ReadCR1();
extern __attribute__((optimize("O0"))) uint32_t ReadCR2();
extern __attribute__((optimize("O0"))) uint32_t ReadCR3();
extern __attribute__((optimize("O0"))) uint32_t WriteCR0(uint32_t cr0);
extern __attribute__((optimize("O0"))) uint32_t WriteCR2(uint32_t cr2);
extern __attribute__((optimize("O0"))) uint32_t WriteCR3(uint32_t cr3);

// descript table register
extern __attribute__((optimize("O0"))) void StoreGDTR(uint64_t gdtinfo);
extern __attribute__((optimize("O0"))) void LoadGDTR(uint16_t limit, uint32_t gdtbase);
extern __attribute__((optimize("O0"))) void StoreIDTR(uint64_t idtinfo);
extern __attribute__((optimize("O0"))) void LoadIDTR(uint16_t limit, uint32_t idtbase);
extern __attribute__((optimize("O0"))) void StoreLDTR(uint64_t ldtinfo);
extern __attribute__((optimize("O0"))) void LoadLDTR(uint16_t limit, uint32_t ldtinfo);

// eflag
extern __attribute__((optimize("O0"))) void LoadEflag(uint32_t eflags);
extern __attribute__((optimize("O0"))) uint32_t StoreEflag();

// cpu operation
extern __attribute__((optimize("O0"))) void CPUhlt();
extern __attribute__((optimize("O0"))) void X86CPUID(uint32_t fun, uint32_t a, uint32_t b, uint32_t c, uint32_t d);
extern __attribute__((optimize("O0"))) void CPUNOP();
extern __attribute__((optimize("O0"))) void X86Invlpg(uint32_t vaddress);

// MSR i/o
extern __attribute__((optimize("O0"))) void ReadMSR(uint32_t id, uint32_t *eax, uint32_t *edx);
extern __attribute__((optimize("O0"))) void WriteMSR(uint32_t id, uint32_t eax, uint32_t edx);

// TSC
extern __attribute__((optimize("O0"))) void _RdTsc(uint32_t *low, uint32_t *high);

static __attribute__((optimize("O0"))) inline uint64_t RdTsc();

static inline uint64_t RdTsc()
{
    volatile uint64_t low, high;

    _RdTsc((intptr_t)&low, (intptr_t)&high);
    return ((uint64_t)high << 32) | low;
}

#define Out8 _Out8
#define Out16 _Out16
#define Out32 _Out32
#define In8 _In8
#define In16 _In16
#define In32 _In32

// x86 lock presuffix
#define LOCK_MEM "lock "
#endif